from django.shortcuts import render
from edoego.models import *
from edoego.serializers import *
from dvadmin.utils.viewset import CustomModelViewSet
from datetime import datetime,timedelta
from rest_framework.decorators import action
from dvadmin.utils.json_response import SuccessResponse, ErrorResponse, DetailResponse
from rest_framework.views import APIView
from threading import Timer
from qiniu import Auth,put_file,etag
import qiniu.config
from django.db.models import Q,FloatField,Sum,F
from django.db.models.functions import Cast
from mqtt_jetlinks import mqtt
import json
import requests
from django.http import FileResponse
from io import BytesIO
from django.utils import timezone
from . import wx_pay
from . import my_utils

class InputLogViewSet(CustomModelViewSet):
    """
    list:查询
    create:新增
    update:修改
    retrieve:单例
    destroy:删除
    """
    authentication_classes = []
    permission_classes = []
    queryset = InputLogModel.objects.all()
    serializer_class = InputLogSerializer
    create_serializer_class = InputLogCreateUpdateSerializer
    update_serializer_class = InputLogCreateUpdateSerializer
    filter_fields = ["input_time","wxuser__phone","wxuser__openid"]
    search_fields = ["wxuser__phone","wxuser__openid"]
    ordering_fields = ["input_time"]

    def get_queryset(self):
        queryset = super().get_queryset()
        phone = self.request.query_params.get('phone')
        openid = self.request.query_params.get('openid')
        print("openid 或者 phone",phone,openid)
        if openid or phone:
            query = Q()
            if openid:
                query |= Q(openid=openid)
            if phone:
                query |= Q(phone=phone)
            user = WechatUserModel.objects.filter(query).first()
            print("user",user)
            if user is not None:
                queryset = queryset.filter(wxuser = user.id)
                return queryset
            return 
    
    def perform_create(self, serializer):
        print("before create",serializer)
        weight = float(serializer.validated_data['input_before_weight'])
        sharing_score = weight * 0.0002
        serializer.validated_data['sharing_score'] = sharing_score
        print("分账：",sharing_score)
        return super().perform_create(serializer)


class InputListViewSet(CustomModelViewSet):
    queryset = InputLogModel.objects.all()
    serializer_class = InputLogSerializer
    create_serializer_class = InputLogCreateUpdateSerializer
    update_serializer_class = InputLogCreateUpdateSerializer
    filter_fields = ["input_time","wxuser__phone","wxuser__openid","device__device_name"]
    search_fields = ["wxuser__phone","wxuser__openid","device__device_name"]
    ordering_fields = ["input_time"]
    def get_queryset(self):
        queryset = super().get_queryset()
        phone = self.request.query_params.get('wxuser[phone]')
        device = self.request.query_params.get('device[device_name]')
        print('phone',phone,device)
        if phone:
            queryset = queryset.filter(wxuser__phone__icontains = phone)
        if device:
            queryset = queryset.filter(device__device_name__icontains=device)
        return queryset

class TotalDataViewSet(CustomModelViewSet):
    authentication_classes = []
    permission_classes = []

    # 今日投放数量
    queryset = InputLogModel.objects.all()
   
    serializer_class = InputLogSerializer
    create_serializer_class = InputLogCreateUpdateSerializer
    update_serializer_class = InputLogCreateUpdateSerializer
    ordering_fields = ["input_time"]
    def get_queryset(self):
        queryset = super().get_queryset()
        today = datetime.datetime.now().date()
        print("今天",today)
        # queryset = queryset.filter(input_time__icontains = today)
        return queryset


class UserPreScore(APIView):
    authentication_classes = []
    permission_classes = []
    def get(self,request):
        phone = request.GET.get("phone")
        openid = request.GET.get("openid")
        userid = request.GET.get('userid')
        # 查询出所有未入账的积分情况
        polls = InputLogModel.objects.annotate(
            pre_float=Cast('user_pre_score',FloatField())
        ).filter(
            Q(wxuser_id=userid),
            Q(pre_float__gt=0)
        ).aggregate(
            toal_score = Sum('pre_float')
        )
        # query = Q(wxuser_id=userid) & Q(user_pre_score__gt=0) & Q(user_score=0)
        print('log',polls)
        return SuccessResponse(data=polls)
    
class DeviceViewSet(CustomModelViewSet):
    authentication_classes = []
    permission_classes = []
    queryset = DeviceModel.objects.all()
    serializer_class = DeviceSerializer
    create_serializer_class = DeviceSerializer
    update_serializer_class = DeviceSerializer

    # user_id = queryset.filter(field='device_user__id')
    filter_fields = ["device_id","device_mac","device_user_id","admin_user_id","device_full_status","device_status"]
    search_fields = ["device_id","device_mac","device_user_id","admin_user_id","device_full_status","device_status"]
    ordering_fields = ["create_datetime"]

    def get_queryset(self):
        queryset = super().get_queryset()
        device_id = self.request.query_params.get('device_id')
        if device_id is not None:
            queryset = queryset.filter(device_id = device_id)
        return queryset
    
class ScanLogViewSet(CustomModelViewSet):
    authentication_classes = []
    permission_classes = []
    queryset = WeChatUserScanModel.objects.all()
    serializer_class = ScanLogSerializer
    create_serializer_class = ScanLogSerializer
    update_serializer_class = ScanLogSerializer

    # user_id = queryset.filter(field='device_user__id')
    ordering_fields = ["create_datetime"]

    def get_queryset(self):
        queryset = super().get_queryset()
        device_id = self.request.query_params.get('device_id')
        if device_id is not None:
            queryset = queryset.filter(device_id = device_id)
            print('queryset',queryset)
        return queryset

class BagViewSet(CustomModelViewSet):
    # 输出大于0
    queryset = BagCodeModel.objects.filter(bag_status__gt=0)
    serializer_class = BagCodeSerializer
    create_serializer_class = BagCodeSerializer
    update_serializer_class = BagCodeSerializer
    filter_fields = ["bag_code","bag_user"]
    search_fields = ["bag_code","bag_user"]
    ordering_fields = ["create_datetime"]

class WeChatUserScoreViewSet(CustomModelViewSet):
    queryset = WxChatUserScoreModel.objects.all()
    serializer_class = WeChatUserScoreSerializer
    create_serializer_class = WeChatUserScoreSerializer
    update_serializer_class = WeChatUserScoreSerializer
    filter_fields = ["phone"]
    search_fields = ["phone"]
    ordering_fields = ["create_datetime"]

class CleanLogViewSet(CustomModelViewSet):
    authentication_classes = []
    permission_classes = []
    queryset = CleanLogModel.objects.all()
    serializer_class = CleanLogSerializer
    create_serializer_class = CleanLogInsertSerializer
    update_serializer_class = CleanLogSerializer
    filter_fields = ["device__device_name","clean_time","user","admin_user","sort_user","clean_status","device_id"]
    search_fields = ["device__device_name","clean_time","user","admin_user","sort_user","clean_status","device_id"]
    ordering_fields = ["create_datetime"]
    def get_queryset(self):
        queryset = super().get_queryset()
        bag_code = self.request.query_params.get('bag_code')
        # 根据code获取id
        bagBean = BagCodeModel.objects.filter(bag_code = bag_code).first()
        if bagBean is not None:
            queryset = queryset.filter(bag_code_id = bagBean)
            print('queryset',queryset)
        return queryset

class WechatUserViewSet(CustomModelViewSet):
    authentication_classes = []
    permission_classes = []
    queryset = WechatUserModel.objects.all()
    serializer_class = WechatUserSerializer
    create_serializer_class = WechatUserSerializer
    update_serializer_class = WechatUserSerializer
    filter_fields = ["phone","openid"]
    search_fields = ["phone","openid"]
    ordering_fields = ["create_datetime"]

class SortLogViewSet(CustomModelViewSet):
    queryset = SortModel.objects.all()
    serializer_class = SortSerializer
    create_serializer_class = SortSerializer
    update_serializer_class = SortSerializer
    filter_fields = ["bag_code","user_id","status"]
    search_fields = ["bag_code","user_id","status"]
    ordering_fields = ["create_datetime"]

# 获取app更新信息
class AppUpdateViewSet(APIView):
    authentication_classes = []
    permission_classes = []
    
    def get(self, request):
        message = self.request.query_params.get('from')
        queryset = AppUpdateModel.objects.filter(message = message).first('create_datetime')
        serializer = AppUpdateSerializer(queryset)
        return DetailResponse({'version':serializer.data})
    
class AppVersonViewSet(CustomModelViewSet):
    authentication_classes = []
    permission_classes = []
    queryset = AppUpdateModel.objects.all()
    serializer_class = AppUpdateSerializer
    create_serializer_class = AppUpdateSerializer
    update_serializer_class = AppUpdateSerializer

# 清运人员开锁
class CleanerOpenBoxView(APIView):
    serializer_class = CleanerOpenBoxSerializer
    authentication_classes = []
    permission_classes = []

    def post(self, request):
        phone = request.data.get("user")
        # 设备号
        device_id = request.data.get("device_id")
        device = request.data.get("device")
        mqtt.unlock(device_id)

        serializer = CleanerOpenBoxSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
        return DetailResponse(data={"msg":"保存成功"})
    

# 扫码投递开箱或者键盘输入手机号 
# 所以需要匹配到相应的用户信息
class WeChatLoginView(APIView):
    serializer_class = ApiWeChatLoginSerializer
    authentication_classes = []
    permission_classes = []

    def post(self, request):
        phone = request.data.get("phone")
        open_id = request.data.get("open_id")
        #device_mac = request.data.get("device_mac")
        device_id = request.data.get("device_id")

        login_success = self.check_login(open_id,phone)
        wxuser_serializer = WechatUserSerializer(login_success)

        if(login_success is not None):
            mqtt.openbox(device_id)
            #插入数据
            mqtt_login_serializer = ScanLogSerializer(data = {
               'openid':login_success.openid,
                'phone':login_success.phone,
                'device_id':device_id
            })
            if mqtt_login_serializer.is_valid():
                mqtt_login_serializer.save()
            return DetailResponse(data=wxuser_serializer.data,msg="登录成功")
        else:
            return ErrorResponse(msg="未注册，请去小程序中注册")

    def check_login(self,openid,phone):
        # 如果数据库中有这个用户，则登录成功，没有则提示在小程序中注册
        if openid or phone:
            query = Q()
            if openid:
                query |= Q(openid=openid)
            if phone:
                query |= Q(phone=phone)
        queryset = WechatUserModel.objects.filter(query)
        if queryset.exists():
            return queryset.first()
        else:
            return None
    

# 获取今日清洁任务情况
class TodayCleanTaskViewSet(CustomModelViewSet):
    queryset = CleanLogModel.objects.all()
    serializer_class = CleanLogSerializer
    filter_fields = ["user__username","create_datetime"]
    search_fields = ["user__username"]
    ordering_fields = ["create_datetime"]

    @action(detail=True,methods=['get'])
    def get_today_clean_task(self,request):
        taskCount = self.queryset.filter(field='user__username').count()
        return SuccessResponse(data={"taskCount":taskCount}, msg="success")
    
class QiniuTokenViewSet(APIView):
    authentication_classes = []
    permission_classes = []

    def get(self, request):
        # 是从工具来的还是垃圾箱来的
        # x_from = request.GET.get('from')
        # 文件格式 图片还是视频
        file_type = request.GET.get("type")
        #获取数据库中数据
        queryset = QiniuImageUpload.objects.first()
        print("获取到的数据",queryset)
        print("ak",queryset.access_key,queryset.secret_key)
        q = Auth(queryset.access_key,queryset.secret_key)
        # 上传空间
        bucket_name = "yiyoutong"
        
        current_datetime = datetime.now()
        current_date_string = current_datetime.strftime('%Y-%m-%d-%H:%M:%S')
        # 上传后保存的文件名
        if(file_type == "jpg"):
            localfile = current_date_string+".jpg"
        else:
            localfile = current_date_string+".mp4"
        token = q.upload_token(bucket_name,None,3600)
        
        return SuccessResponse(data={"token":token,"file_type":file_type,"file_name":localfile}, msg="success")
    

class ImageViewSet(CustomModelViewSet):
    authentication_classes = []
    permission_classes = []
    queryset = ImageModel.objects.all()
    serializer_class = ImageSerializer
    create_serializer_class = ImageSerializer
    update_serializer_class = ImageSerializer
    filter_fields = ["create_datetime"]
    search_fields = ["create_datetime","input__id","sort__id","clean__id"]
    ordering_fields = ["create_datetime","input__id","sort__id","clean__id"]


class WxAccessTokenViewSet(APIView):
    authentication_classes = []
    permission_classes = []

    def get(self, request):
        # 请求微信
        url = 'https://api.weixin.qq.com/cgi-bin/token'
        params = {
            'grant_type':'client_credential',
            'appid':'wxe8411de4faf8fb57',
            'secret':'f29229ee3e50aab2ed4bc862a897d526'
        }
        response = requests.get(url,params=params)
        print("response",response)
        return SuccessResponse(data=response)

class WxQrcode(APIView):
    authentication_classes = []
    permission_classes = []

    def post(self, request):
        device_id = request.data.get("device_id")
        print("device",device_id)
        # 请求获取token
        url_token = 'https://api.weixin.qq.com/cgi-bin/token'
        params_token = {
            'grant_type':'client_credential',
            'appid':'wxe8411de4faf8fb57',
            'secret':'f29229ee3e50aab2ed4bc862a897d526'
        }
        token_response = requests.get(url_token,params=params_token)
        token_Json = token_response.json()
        token = token_Json.get('access_token')

        
        print("token",token)
        url = 'https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token='+token
        print("请求api",url)
        params = {
            'page':'pages/index/index',
            'scene':device_id,
            "env_version":"release"
            # 'env_version':'develop'
        }
        response = requests.post(url,json=params)
        image_buffer = BytesIO(response.content)
        image_buffer.seek(0)  # 重置缓冲区位置到开始

        # 返回 FileResponse
        return FileResponse(image_buffer, content_type=response.headers.get('Content-Type'))  # 根据需要设置文件名

class WxOpenId(APIView):
    def get(self,request):
        jsCode = request.GET.get("jsCode")

        url = 'https://api.weixin.qq.com/sns/jscode2session'
        params = {
            'appid':'wxe8411de4faf8fb57',
            'secret':'f29229ee3e50aab2ed4bc862a897d526',
            'js_code':jsCode,
            'grant_type': 'authorization_code'
        }
        response = requests.get(url,params=params)
        print('openId',response)
        return SuccessResponse(data=response)
    

class WxPayViewSet(APIView):
    authentication_classes = []
    permission_classes = []
    def post(self,request):
        openid = request.data.get("openid")
        phone = request.data.get("phone")
        money = request.data.get("money")
        money_float = float(money)
        print("money_float",money_float)
        # 要查看这个人是否有这么多钱
        user = WechatUserModel.objects.filter(openid=openid).first()
        user_score = float(user.score)
        if user_score < money_float :
            return ErrorResponse(msg="您当前没有这么多余额！")

        trade_no = my_utils.generate_order_id()
        response = wx_pay.transfer_to_user(wx_pay.wxpay,money_float*100,trade_no,openid,phone)
        # 如果受理，则消耗掉用户积分
        print("response:",response)
        status_code,json_string = response
        
        if status_code:
            data = json.loads(json_string)
            batch_status = data.get('batch_status')
            batch_id = data.get('batch_id')
            out_batch_no = data.get('out_batch_no')

            if batch_status == "ACCEPTED":
                money_result = format(float(user.score)-money_float,".2f")
              
                data = {
                    'score': money_result,
                    'phone': phone,
                    'openid':openid
                }
                userSerialzer = WechatUserSerializer(user,data=data)
                print("userserial",userSerialzer)
                if userSerialzer.is_valid():
                    userSerialzer.save()

                data_score = {
                    'phone':phone,
                    'openid':openid,
                    'score':money,
                    'score_type':'提现',
                    'batch_id': batch_id,
                    'out_batch_no': out_batch_no
                }
                score_log = WeChatUserScoreSerializer(data=data_score)
                if score_log.is_valid():
                    score_log.save()

        return DetailResponse(data=response)
    

# 前台的信息入库
# 注意要保证数据正确！
class UserPreToScore(APIView):
    authentication_classes = []
    permission_classes = []
    # 查询出前天的账单
    def get(self, request, format=None):
        # 获取前天的日期
        yesterday = timezone.now() - timedelta(days=1)
        the_day_before_yesterday = yesterday - timedelta(days=1)
        
        # 查询前天的记录
        # 过滤掉这两台设备
        input_logs = InputLogModel.objects.filter(
            Q(input_time__date=the_day_before_yesterday.date())&
            ~Q(device_id = 61)  &
            ~Q(device_id = 39)  
            )
        #input_logs = InputLogModel.objects.filter(input_time__date=the_day_before_yesterday.date())
        for input_log in input_logs:
        # 获取对应的用户信息
            wechat_user = input_log.wxuser
            # 更新InputLogModel实例
            input_log.user_score = input_log.user_pre_score
            input_log.user_pre_score = 0
            input_log.save()

            # 累加用户的score，假设score是字符串类型，需要转换为float进行计 算
            if wechat_user.score:
                print("score:",wechat_user.score)
                print("input score:",input_log.user_score)
                # format(float(user.score)-money_float,".2f")
                new_score = float(wechat_user.score) + float(input_log.user_score)
                print("new score:",new_score)
                new_score_format = "{:.2f}".format(new_score)
                wechat_user.score = str(new_score_format)
                print("new score",wechat_user.score)
                wechat_user.save()
        
                # 返回响应
        return DetailResponse(data={"msg":"保存成功"})
    
# 查看已经分账，但是未进账的数据，48小时外，也就是可以提现的数据
class SharingUnCheck(APIView):
    authentication_classes = []
    permission_classes = []
    def post(self,request):
        phone = request.data.get('phone')

        # 获取前天的日期
        forty_eight_hours_ago = datetime.now() - timedelta(days=2)
        # 根据人查到设备
        devices = DeviceModel.objects.filter(sharing_user=phone)
        if not devices:
            return ErrorResponse(msg="暂无设备")
        # 设备id
        device_ids  = devices.values_list('id',flat=True)
        # 根据设备查到订单
        input_log = InputLogModel.objects.filter(
            Q(input_time__date__lt = forty_eight_hours_ago) &
            Q(device_id__in = device_ids) &
            Q(sharing_score__gt = 0)
        )
        print('query',input_log.query)
        total_sharing_score = input_log.aggregate(Sum('sharing_score'))['sharing_score__sum']
        if total_sharing_score is None:
            total_sharing_score = 0
        print("总和:", total_sharing_score)
        return DetailResponse(data={
            "total":total_sharing_score
        })
    
# 查看这两天的分账，48小时内，但未提现的数据
class SharingUnCheckToday(APIView):
    authentication_classes = []
    permission_classes = []
    def post(self,request):
        phone = request.data.get('phone')

        forty_eight_hours_ago = datetime.now() - timedelta(days=2)
        # 根据人查到设备
        devices = DeviceModel.objects.filter(sharing_user=phone)
        if not devices:
            return ErrorResponse(msg="暂无设备")
        # 设备id
        device_ids  = devices.values_list('id',flat=True)
        # 根据设备查到订单
        input_log = InputLogModel.objects.filter(
            Q(input_time__date__gt = forty_eight_hours_ago) &
            Q(device_id__in = device_ids) &
            Q(sharing_score__gt = 0)
        )
        total_sharing_score = input_log.aggregate(Sum('sharing_score'))['sharing_score__sum']
        if total_sharing_score is None:
            total_sharing_score = 0
        print("总和:", total_sharing_score)
        return DetailResponse(data={
            "total":total_sharing_score
        })
# 今天的账单
# 设备名，投放次数，投放重量总计，未入账总计
class SharingUnCheckTodayData(APIView):
    authentication_classes = []
    permission_classes = []
    def post(self,request):
        phone = request.data.get('phone')

        forty_eight_hours_ago = datetime.now() - timedelta(days=2)
        # 根据人查到设备
        devices = DeviceModel.objects.filter(sharing_user=phone)
        if not devices:
            return ErrorResponse(msg="暂无设备")
        # 设备id
        # device_ids  = devices.values_list('id',flat=True)

        # 根据设备查到订单
        # input_log = InputLogModel.objects.filter(
        #     Q(input_time__date__gt = forty_eight_hours_ago) &
        #     Q(device_id__in = device_ids) &
        #     Q(sharing_score__gt = 0)
        # )
        response_data = []

        for device in devices:
            inputs = InputLogModel.objects.filter(
                Q(device_id = device.id) &
                Q(input_time__date__gt = forty_eight_hours_ago) &
                Q(sharing_score__gt = 0)
            )
            total_count = inputs.count()
            total_weight = inputs.aggregate(Sum('input_before_weight'))['input_before_weight__sum'] or 0
            total_amount = inputs.aggregate(Sum('sharing_score'))['sharing_score__sum'] or 0

        
            serializer = InputLogSerializer(inputs,many=True).data

            device_data = {
                'device_name': device.device_name,
                'total_count': total_count,
                'total_weight': total_weight,
                'total_amount': total_amount,
                'inputs': serializer
            }

            response_data.append(device_data)
        
        return DetailResponse(data={
            "data":response_data
        })

class SharingChecked(APIView):
    authentication_classes = []
    permission_classes = []
    def post(self,request):
        phone = request.data.get('phone')

        devices = DeviceModel.objects.filter(sharing_user=phone)
        if not devices:
            return ErrorResponse(msg="暂无设备")
        # 设备id
        device_ids  = devices.values_list('id',flat=True)
        # 根据设备查到订单
        input_log = InputLogModel.objects.filter(
            Q(device_id__in = device_ids) &
            Q(sharing_score_checked__gt = 0)
        )
        total_sharing_score = input_log.aggregate(Sum('sharing_score_checked'))['sharing_score_checked__sum']
        if total_sharing_score is None:
            total_sharing_score = 0
        print("总和:", total_sharing_score)
        return DetailResponse(data={
            "total":total_sharing_score
        })

# 分账提现
class SharingWxPayViewSet(APIView):
    authentication_classes = []
    permission_classes = []
    def post(self,request):
        openid = request.data.get("openid")
        phone = request.data.get('phone')
        if openid is None:
            return ErrorResponse(msg="openid 为空")
        # 获取前天的日期
        forty_eight_hours_ago = datetime.now() - timedelta(days=2)
        # 根据人查到设备
        devices = DeviceModel.objects.filter(sharing_user=phone)
        if not devices:
            return ErrorResponse(msg="暂无设备")
        # 设备id
        device_ids  = devices.values_list('id',flat=True)
        # 根据设备查到订单
        input_log = InputLogModel.objects.filter(
            Q(input_time__date__lt = forty_eight_hours_ago) &
            Q(device_id__in = device_ids) &
            Q(sharing_score__gt = 0)
        )
        total_sharing_score = input_log.aggregate(Sum('sharing_score'))['sharing_score__sum']
        if total_sharing_score is None:
            total_sharing_score = 0
            return ErrorResponse(msg="暂无提现")
        total_str = str(total_sharing_score*100)
        trade_no = my_utils.generate_order_id()
        response = wx_pay.transfer_to_user(wx_pay.wxpay,total_str,trade_no,openid,phone)
        # 如果受理，则消耗掉用户积分
        print("response:",response)
        status_code,json_string = response
        
        if status_code:
            data = json.loads(json_string)
            batch_status = data.get('batch_status')
            batch_id = data.get('batch_id')
            out_batch_no = data.get('out_batch_no')

            if batch_status == "ACCEPTED":
                #将订单的sharing_score 变为sharing_score_checked
                input_log.update(
                    sharing_score_checked = F('sharing_score'),
                    sharing_score = 0
                )

        return DetailResponse(data=response)